package com.yuelife.common.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.IOUtils;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.UUID;

/**
 * @program: ysh
 * @description: 阿里云oss服务相关工具类
 * @author: Tanxu
 * @create: 2020-05-08 11:28
 **/
@Component
@Slf4j
public class AliyunOSSUtil {
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(AliyunOSSUtil.class);
    private static String FILE_URL;
    //仓库名称
    private static String bucketName ="yuelife2020";
    //地域节点
    private static String endpoint = "http://oss-cn-beijing.aliyuncs.com";
    //AccessKey ID
    private static String accessKeyId = "LTAI4G1Xqg2RfD8C6NYPQMZ8";
    //Access Key Secret
    private static String accessKeySecret = "PGcDoe3MTQlNgrN4gTnk3pR9t3QOPO";
    //仓库中的某个文件夹
    private static String fileHost = "service";
    /**
     * 斜杠
     */
    private final String FLAG_SLANTING_ROD = "/";
    /**
     * http://
     */
    private final String FLAG_HTTP = "http://";
    /**
     * https://
     */
    private final String FLAG_HTTPS = "https://";
    /**
     * 空字符串
     */
    private final String FLAG_EMPTY_STRING = "";
    /**
     * 点号
     */
    private final String FLAG_DOT = ".";
    /**
     * 横杠
     */
    private final String FLAG_CROSSBAR = "-";

    /**
     * 缺省的最大上传文件大小：5M
     */
    private final int DEFAULT_MAXIMUM_FILE_SIZE = 5;

    /**
     * 以文件流的方式上传文件
     *
     * @return
     */
    public String uploadFile(InputStream inputStream) {
        return coreUpload(UUID.randomUUID().toString().replace("-","")+".jpg", "", inputStream);
    }

    private String coreUpload(String fileName, String filePath, InputStream inputStream) {
        log.info("Start to upload file....");
        String fileUrl;
        OSSClient ossClient = null;
        try {

            // If the upload file size exceeds the limit
            long maxSizeAllowed = getMaximumFileSizeAllowed();
            if (Long.valueOf(inputStream.available()) > maxSizeAllowed) {
                log.error("Uploaded file is too big.");
                return null;
            }

            // Create OSS instance
            ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);

            // Create bucket if not exists
            if (!ossClient.doesBucketExist(bucketName)) {
                log.info("Bucket '{}' is not exists and create it now.", bucketName);
                ossClient.createBucket(bucketName);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossClient.createBucket(createBucketRequest);
            }

            /*********************************/
            // List the bucket in my account
            //listBuckets(ossClient);
            /*********************************/

            // File path format
            if (!filePath.startsWith(FLAG_SLANTING_ROD)) {
                filePath = FLAG_SLANTING_ROD.concat(filePath);
            }
            if (!filePath.endsWith(FLAG_SLANTING_ROD)) {
                filePath = filePath.concat(FLAG_SLANTING_ROD);
            }

            // File url
            StringBuilder buffer = new StringBuilder();
            buffer.append(fileHost).append(filePath).append(fileName);
            fileUrl = buffer.toString();
            log.info("After format the file url is {}", fileUrl);

            // Upload file and set ACL
            PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, inputStream));
            ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            if (result != null) {
                log.info("Upload result:{}", result.getETag());
                log.info("Upload file {} successfully.", fileName);
            }
            fileUrl = getHostUrl().concat(fileUrl);
            log.info("Call path is {}", fileUrl);

            /***********************************/
            // List objects in your bucket
            //listObjects(ossClient);
            /***********************************/

        } catch (Exception e) {
            log.error("Upload file failed.", e);
            fileUrl = null;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return fileUrl;
    }

    /**
     * 列出buckets下的所有文件
     *
     * @param ossClient
     */
    private void listObjects(OSSClient ossClient) {
        System.out.println("Listing objects");
        ObjectListing objectListing = ossClient.listObjects(bucketName);
        for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
            System.out.println(" - " + objectSummary.getKey() + "  " +
                    "(size = " + objectSummary.getSize() + ")");
        }
        System.out.println();
    }

    /**
     * 列出当前用户下的所有bucket
     *
     * @param ossClient
     */
    private void listBuckets(OSSClient ossClient) {
        System.out.println("Listing buckets");
        ListBucketsRequest listBucketsRequest = new ListBucketsRequest();
        listBucketsRequest.setMaxKeys(500);
        for (Bucket bucket : ossClient.listBuckets()) {
            System.out.println(" - " + bucket.getName());
        }
        System.out.println();
    }

    /**
     * 以文件的形式上传文件
     */
    public String uploadFile( File file) {
        String fileName= UUID.randomUUID().toString().replace("-","")+".jpg";
        String filePath="";
        if (file == null) {
            log.warn("File is lack when upload.");
            return null;
        }

        InputStream inputStream = null;
        String fileUrl = null;
        try {
            inputStream = new FileInputStream(file);
            fileUrl = uploadFile(inputStream);
        } catch (Exception e) {
            log.error("Upload file error.", e);
        } finally {
            IOUtils.safeClose(inputStream);
        }
        return fileUrl;
    }

    /**
     * 获取访问的base地址
     */
    private String getHostUrl() {
        String hostUrl = null;
        if (AliyunOSSUtil.endpoint.startsWith(FLAG_HTTP)) {
            hostUrl = FLAG_HTTP.concat(AliyunOSSUtil.bucketName).concat(FLAG_DOT)
                    .concat(AliyunOSSUtil.endpoint.replace(FLAG_HTTP, FLAG_EMPTY_STRING)).concat(FLAG_SLANTING_ROD);
        } else if (AliyunOSSUtil.endpoint.startsWith(FLAG_HTTPS)) {
            return FLAG_HTTPS.concat(AliyunOSSUtil.bucketName).concat(FLAG_DOT)
                    .concat(AliyunOSSUtil.endpoint.replace(FLAG_HTTPS, FLAG_EMPTY_STRING)).concat(FLAG_SLANTING_ROD);
        }
        return hostUrl;
    }

    /**
     * 获取最大允许上传文件的大小
     *
     * @return
     */
    private long getMaximumFileSizeAllowed() {
        return DEFAULT_MAXIMUM_FILE_SIZE * 1024L * 1024L;
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件访问的全路径
     */
    public void deleteFile(String fileUrl) {
        log.info("Start to delete file from OSS.{}", fileUrl);
        if (StringUtils.isEmpty(fileUrl)
                || (!fileUrl.startsWith(FLAG_HTTP)
                && !fileUrl.startsWith(FLAG_HTTPS))) {
            log.error("Delete file failed because the invalid file address. -> {}", fileUrl);
            return;
        }
        OSSClient ossClient = null;
        try {
            /**
             * http:// bucketname                                dev/test/pic/abc.jpg = key
             * http:// captainad.oss-ap-southeast-.aliyuncs.com/dev/test/pic/abc.jpg
             */
            String key = fileUrl.replace(getHostUrl(), FLAG_EMPTY_STRING);
            if (log.isDebugEnabled()) {
                log.debug("Delete file key is {}", key);
            }
            ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
            ossClient.deleteObject(bucketName, key);
        } catch (Exception e) {
            log.error("Delete file error.", e);
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

